package edu.uci.ics.multicast.overlay;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

public class Topology {
	
	private List<OverlayNode> listOverlayNodes = new LinkedList<OverlayNode>();
	private List<PhysicalNode> lisPhysicalNodes = new LinkedList<PhysicalNode>();
	private List<Edge> listEdges = new LinkedList<Edge>();
	 
	private HashMap<String,MulticastNode> hashIndexToNode = new HashMap<String, MulticastNode>();
	private HashMap<String,OverlayNode> hashVirtualIndexToNode = new HashMap<String, OverlayNode>();
	private HashMap<String,Edge> hashIndexToEdge = new HashMap<String, Edge>();

	public double getLatency(OverlayNode source, OverlayNode destination) {
		if (source!=null && destination!=null) {
			List<Path> listPaths = source.getListPath();
			for (Path path : listPaths) {
				if (path.getDestinationNode().equals(destination)) {
					double latency = 0;
					List<Edge> aListEdges = path.getListEdges();
					for (Edge edge : aListEdges) {
						latency += edge.getLatency();
					}
					return latency;
				}
				
			}
		}
		return Double.MAX_VALUE;
	}

	public void addOverlayNode(OverlayNode overlayNode) {
		listOverlayNodes.add(overlayNode);
		hashIndexToNode.put(overlayNode.getIndex(), overlayNode);
		hashVirtualIndexToNode.put(overlayNode.getVirtualIndex(), overlayNode);
	}

	public void addPhysicalNode(PhysicalNode physicalNode) {
		lisPhysicalNodes.add(physicalNode);	
		hashIndexToNode.put(physicalNode.getIndex(), physicalNode);
	}

	public void addEdge(Edge edge) {
		listEdges.add(edge);
		hashIndexToEdge.put(edge.getIndex(), edge);
	}
	
	public MulticastNode getMulticastNode(String index) {
		return hashIndexToNode.get(index);
	}
	
	public OverlayNode getOverlayNodeByIndex(String index) {
		return (OverlayNode) hashIndexToNode.get(index);
	}
	
	public OverlayNode getOverlayNodeByVirtualIndex(String virtualIndex) {
		return hashVirtualIndexToNode.get(virtualIndex);
	}

	public Edge getEdgeByIndex(String index) {
		return hashIndexToEdge.get(index);
	}

	public List<OverlayNode> getListOverlayNodes() {
		return listOverlayNodes;
	}
	
	public List<PhysicalNode> getListPhysicalNodes(OverlayNode source, OverlayNode destination) {
		List<PhysicalNode> aListPhysicalNodes = new LinkedList<PhysicalNode>();
		if (source!=null && destination!=null) {
			List<Path> listPaths = source.getListPath();
			for (Path path : listPaths) {
				if (path.getDestinationNode().equals(destination)) {
					List<Edge> aListEdges = path.getListEdges();
					for (Edge edge : aListEdges) {
						MulticastNode node = edge.getSource();
						if (node instanceof PhysicalNode) {
							PhysicalNode physicalNode = (PhysicalNode) node;
							aListPhysicalNodes.add(physicalNode);
						}
					}
					return aListPhysicalNodes;
				}
			}
		}
		return null;
	}

}
